﻿using System;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows;
using System.Collections.Generic;
using System.ComponentModel;

namespace WickedFlame.GenDock
{
    public class ButtonAnchor : Anchor, IDockableWindowPresenter
    {
        List<DockableWindow> windows;

        public ButtonAnchor()
            : base()
        {
            windows = new List<DockableWindow>();
        }

        public bool IsMultyWindow
        {
            get
            {
                return (bool)GetValue(IsMultyWindowProperty);
            }
            set
            {
                SetValue(IsMultyWindowProperty, value);
            }
        }

        public static readonly DependencyProperty IsMultyWindowProperty =
            DependencyProperty.Register("IsMultyWindow", typeof(bool), typeof(ButtonAnchor), new PropertyMetadata(true));

        #region Anchor Member

        public override void AddContent(ContentDocument content)
        {
            var btn = new ButtonAnchorButton();
            btn.Width = content.Width;
            btn.Height = 27;
            btn.Width = 30;

            btn.Icon = content.Icon;
            btn.Title = content.Title;
            btn.Click += new RoutedEventHandler(OnClicked);
            VisibleChildren.Add(btn);

            content.Visibility = Visibility.Visible;

            AddContent(btn, content);

            InvalidateContent();
        }

        public override void AddContent(ContentDocument content, Point point)
        {
            int index = 0;
            //double x = System.Windows.Input.Mouse.GetPosition(Window.GetWindow(this));
            for (int i = 0; i < VisibleChildren.Count; i++)
            {
                //x += this.VisibleChildren[i].Height;
                //x += (this.VisibleChildren[i] as ButtonAnchorButton).Margin.Top;
                //x += (this.VisibleChildren[i] as ButtonAnchorButton).Margin.Bottom;

                //if (x > point.Y)
                //    break;

                System.Windows.Media.GeneralTransform transform = VisibleChildren[i].TransformToAncestor(Window.GetWindow(this.Parent));
                Point rootPoint = transform.Transform(new Point(0, 0));

                var rect = new Rect(rootPoint.X, rootPoint.Y, VisibleChildren[i].RenderSize.Width, VisibleChildren[i].RenderSize.Height);

                if (point.Y < rect.Y)
                    break;

                index = i;
            }


            var btn = new ButtonAnchorButton();
            btn.Width = content.Width;
            btn.Height = 27;
            btn.Width = 30;

            btn.Icon = content.Icon;
            btn.Title = content.Title;
            btn.Click += new RoutedEventHandler(OnClicked);
            VisibleChildren.Insert(index, btn);

            content.Visibility = Visibility.Visible;

            AddContent(btn, content);

            InvalidateContent();
        }

        public override void RemoveContent(ContentDocument content)
        {
            foreach (ButtonAnchorButton button in listContents.Keys)
            {
                if (listContents[button] == content)
                {
                    this.VisibleChildren.Remove(button);
                    this.listContents.Remove(button);
                    this.InvalidateContent();
                    break;
                }
            }
        }

        public override bool ShowContent(Type type)
        {
            foreach (ButtonAnchorButton button in listContents.Keys)
            {
                Type t = listContents[button].GetType();
                if (t == type)
                {
                    button.IsSelected = true;
                    OnClicked(button, new RoutedEventArgs());
                    return true;
                }
            }

            return false;
        }

        public override bool ShowContent(ContentDocument content)
        {
            foreach (ButtonAnchorButton button in listContents.Keys)
            {
                if (listContents[button] == content)
                {
                    button.IsSelected = true;
                    OnClicked(button, new RoutedEventArgs());
                    return true;
                }
            }

            return false;
        }

        #endregion

        #region IDockableWindowPresenter Member

        public void RepositionDockedWindow()
        {
            if (windows.Count == 0)
                return;

            PositionWindows();
        }

        public void ReleaseDockedWindow(DockableWindow wnd)
        {
            ContentDocument content = wnd.Content as ContentDocument;
            if (content != null)
            {
                RemoveContent(content);
                
                if (content.Parent is DockableWindow)
                {
                    windows.Remove(wnd);
                }

                content.AnchorPlace = AnchorType.None;
                wnd.Closed -= new EventHandler(OnWindowClosed);
                wnd.Closing -= new CancelEventHandler(OnWindowClosing);
            }
        }

        #endregion

        private void OnClicked(object sender, RoutedEventArgs e)
        {
            //close the visible windows if ther is only one allowed
            if (!IsMultyWindow)
            {
                while (windows.Count > 0)
                {
                    windows[0].Close();
                }

                foreach (ButtonBase button in listContents.Keys)
                {
                    if (button != (sender as ButtonBase) && button.IsSelected)
                        button.IsSelected = false;
                }

                if ((sender as ButtonBase).IsSelected)
                {
                    ContentDocument content = listContents[sender as ButtonBase];
                    var window = new DockableWindow();
                    window.AddContent(content);
                    window.Owner = Window.GetWindow(this);

                    window.Title = content.Title;

                    windows.Add(window);

                    window.Closing += new CancelEventHandler(OnWindowClosing);
                    window.Closed += new EventHandler(OnWindowClosed);
                    window.CollapseChanged += new EventHandler(OnWindowCollapseChanged);

                    window.Show();

                    //set position of window
                    PositionWindows();
                }
            }
            else
            {
                // close window if it is not selected
                if (!(sender as ButtonBase).IsSelected)
                {
                    DockableWindow tmp = null;
                    foreach (DockableWindow window in windows)
                    {
                        ContentDocument content = listContents[sender as ButtonBase];

                        if ((window.Content as ContentDocument) == content)
                        {
                            tmp = window;
                            break;
                        }
                    }
                    if (tmp != null)
                        tmp.Close();
                    return;
                }

                // do nothing if window already exists (just for safety...)
                foreach (DockableWindow window in windows)
                {
                    ContentDocument content = listContents[sender as ButtonBase];

                    if ((window.Content as ContentDocument) == content)
                    {
                        (window as DockableWindow).IsCollapsed = false;
                        return;
                    }
                }


                if ((sender as ButtonBase).IsSelected)
                {
                    ContentDocument content = listContents[sender as ButtonBase];
                    var window = new DockableWindow();
                    window.AddContent(content);
                    window.Owner = Window.GetWindow(this);

                    window.Title = content.Title;
                    
                    windows.Add(window);

                    window.Closing += new CancelEventHandler(OnWindowClosing);
                    window.Closed += new EventHandler(OnWindowClosed);
                    window.CollapseChanged += new EventHandler(OnWindowCollapseChanged);

                    window.Show();

                    //set position of window
                    PositionWindows();
                }
            }
        }

        private void PositionWindows()
        {
            double y = 0.0;

            foreach (ButtonBase btn in listContents.Keys)
            {
                if (btn.IsSelected)
                {
                    //select first
                    if (y == 0.0)
                    {
                        DockableWindow window = null;

                        foreach (DockableWindow wnd in windows)
                        {
                            ContentDocument content = listContents[btn];

                            if ((wnd.Content as ContentDocument) == content)
                                window = wnd;
                        }

                        if (window != null)
                        {
                            GeneralTransform transform = btn.TransformToAncestor(this);
                            Point rootPoint = transform.Transform(new Point(0, 0));
                            Point p = this.PointToScreen(rootPoint);
                            window.Top = p.Y;
                            window.Left = p.X - (listContents[btn].Width + btn.Margin.Left + 4);

                            y = window.Top + window.ActualHeight;
                        }
                    }
                    else
                    {
                        DockableWindow window = null;

                        foreach (DockableWindow wnd in windows)
                        {
                            ContentDocument content = listContents[btn];

                            if ((wnd.Content as ContentDocument) == content)
                                window = wnd;
                        }

                        if (window != null)
                        {
                            GeneralTransform transform = btn.TransformToAncestor(this);
                            Point rootPoint = transform.Transform(new Point(0, 0));
                            Point p = this.PointToScreen(rootPoint);
                            window.Top = y;
                            window.Left = p.X - (listContents[btn].Width + btn.Margin.Left + 4);

                            y = window.Top + window.ActualHeight;
                        }
                    }
                }
            }
        }

        private void OnWindowClosing(object sender, CancelEventArgs e)
        {
            DockableWindow window = sender as DockableWindow;
            if (window != null)
            {
                foreach (ButtonBase button in listContents.Keys)
                {
                    if (listContents[button] == window.Content)
                        button.IsSelected = false;
                }
            }
        }

        private void OnWindowClosed(object sender, EventArgs e)
        {
            DockableWindow window = sender as DockableWindow;
            if (window != null)
            {
                windows.Remove(window);
                try
                {
                    PositionWindows();
                }
                catch { }

                window.Dispose();
                window = null;

                
            }
        }

        private void OnWindowCollapseChanged(object sender, EventArgs e)
        {
            PositionWindows();
        }
    }
}
